// ObservableWorker.cs
// ------------------------------------------------------------------
//
// Description goes here....
//
// Author     : Dino
// Created    : Thu Aug 25 17:37:20 2011
// Last Saved : <2011-October-22 19:13:45>
//
// ------------------------------------------------------------------
//
// Copyright (c) 2011 by Dino Chiesa
// All rights reserved!
//
// ------------------------------------------------------------------

using System;
using System.Threading;
using System.ComponentModel;


namespace C4Tools.ML2
{
    internal abstract class ObservableWorker : IProgressWorker
    {
        protected int _total;
        protected string _stage;
        protected int _current;
        protected bool _isCancelationPending;

        public ObservableWorker()
        {
            this._total = 0;
            this._current = 0;
            this._isCancelationPending = false;
        }

        public virtual void DoWork(object sender, DoWorkEventArgs e)
        {
        }

        public virtual void WorkCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            OnComplete(EventArgs.Empty);
        }


        protected virtual void OnStageChanged(EventArgs e)
        {
            if (this.StageChanged != null)
            {
                this.StageChanged(this, e);
            }
        }

        protected virtual void OnProgressChanged(EventArgs e)
        {
            if (this.ProgressChanged != null)
            {
                this.ProgressChanged(this, e);
            }
        }

        protected virtual void OnProgressTotalChanged(EventArgs e)
        {
            if (this.ProgressTotalChanged != null)
            {
                this.ProgressTotalChanged(this, e);
            }
        }

        protected virtual void OnComplete(EventArgs e)
        {
            if (this.Complete != null)
            {
                this.Complete(this, e);
            }
        }


        #region IProgressOperation Members

        public int Total
        {
            get
            {
                return this._total;
            }
            protected set
            {
                this._total = value;
                OnProgressTotalChanged(EventArgs.Empty);
            }
        }

        public int Current
        {
            get
            {
                return this._current;
            }
            protected set
            {
                this._current = value;
                OnProgressChanged(EventArgs.Empty);
            }
        }

        public String Stage
        {
            get
            {
                return this._stage;
            }
            protected set
            {
                this._stage = value;
                OnStageChanged(EventArgs.Empty);
            }
        }


        /// <summary>
        /// Starts the operation on a BackgroundWorker
        /// </summary>
        public void Start()
        {
            this.Start(false);
        }

        /// <summary>
        /// Starts the operation, maybe on a BackgroundWorker
        /// </summary>
        public void Start(bool wantSta)
        {
            if (wantSta)
            {
                var bgThread = new Thread(delegate() {
                            DoWork(null, null);
                            // want to run WorkCompleted on the main thread, but
                            // only after the work is done. I will rely on
                            // the event sink to handle thread fixups.
                            WorkCompleted(null,null);
                        });
                bgThread.SetApartmentState(ApartmentState.STA);
                bgThread.Start();
            }
            else
            {
                BackgroundWorker worker = new BackgroundWorker();
                worker.DoWork += new DoWorkEventHandler(DoWork);
                worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(WorkCompleted);
                worker.RunWorkerAsync();
            }
        }


        /// <summary>
        /// Requests cancelation of the event log exporting
        /// </summary>
        public void CancelAsync()
        {
            this._isCancelationPending = true;
        }

        public event EventHandler StageChanged;
        public event EventHandler ProgressChanged;
        public event EventHandler ProgressTotalChanged;
        public event EventHandler Complete;

        #endregion

    }
}
